package com.fyp.ptma.dao.repository;

import java.util.List;

import javax.persistence.PersistenceException;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.fyp.ptma.dao.repository.irepository.IApplicationDao;
import com.fyp.ptma.model.Application;
import com.fyp.ptma.model.ApplicationVersion;
import com.fyp.ptma.model.ApplicationVersionPk;
import com.fyp.ptma.model.Downloader;

/**
 * 
 * @author YahyaArshad
 * 
 */

@Repository
public class ApplicationDao implements IApplicationDao {
	@Autowired
	private SessionFactory sessionFactory;

	public Long save(Object objToSave) throws PersistenceException,
			ConstraintViolationException {
		Session session = this.openSession();

		session.save(objToSave);

		return 1L;
	}

	public Long save(Application objToSave) throws PersistenceException,
			ConstraintViolationException {
		Session session = this.openSession();

		for (ApplicationVersion version : objToSave.getAppVersions()) {
			Long id = version.getId();
			if (id == null) {
				Number dbId = (Number) session.createQuery(
						"select max(id) from ApplicationVersion")
						.uniqueResult();
				if (dbId == null) {
					dbId = 0L;
				}
				long lDbId = (dbId.longValue());
				lDbId++;
				version.setId(lDbId);

			}
		}

		session.saveOrUpdate(objToSave);

		return 1L;
	}

	public Long save(ApplicationVersion objToSave) throws PersistenceException,
			ConstraintViolationException {

		Session session = this.openSession();
		Long id = objToSave.getId();
		if (id == null) {
			Number dbId = (Number) session.createQuery(
					"select max(id) from ApplicationVersion").uniqueResult();
			if (dbId == null) {
				dbId = 0L;
			}
			long lDbId = (dbId.longValue());
			lDbId++;
			objToSave.setId(lDbId);

		}

		session.saveOrUpdate(objToSave);

		return 1L;
	}

	public Long update(Object objToUpdate) throws PersistenceException {
		// TODO Auto-generated method stub
		return null;
	}

	public boolean delete(Object objToDelete) throws PersistenceException,
			ConstraintViolationException {
		this.openSession().delete(objToDelete);
		return true;
	}

	@SuppressWarnings("unchecked")
	public List<ApplicationVersion> getAllApplicationVersions(
			Application application) throws HibernateException {
		Session session = this.openSession();
		Criteria criteria = session.createCriteria(ApplicationVersion.class)
				.add(Restrictions.eq("application", application));
		List<ApplicationVersion> appVersions = criteria.list();
		return appVersions;
	}

	public boolean deleteApplicationVersion(ApplicationVersion appVersion)
			throws HibernateException {
		// TODO Auto-generated method stub
		return false;
	}

	public Application getApplicationByUserAndNameSpace(String userEmail,
			String nameSpace) throws HibernateException {
		Session session = this.openSession();
		Query query = session
				.createSQLQuery(
						"select {app.*} from Application as app inner join User user on user.email = :userEmail and user.Id = app.user_id and app.nameSpace = :nameSpace")
				.addEntity("app", Application.class);
		query.setParameter("userEmail", userEmail);
		query.setParameter("nameSpace", nameSpace);

		return (Application) query.uniqueResult();

	}

	@Override
	public Session openSession() {
		// TODO Auto-generated method stub
		return sessionFactory.getCurrentSession();
	}

	@Override
	public void saveOrUpdate(Object objToSave) throws PersistenceException,
			ConstraintViolationException {
		Session session = this.openSession();

		session.save(objToSave);

	}

	public ApplicationVersion getApplicationVersionByPk(
			ApplicationVersionPk versionPk, String devEmail)
			throws HibernateException {
		Session session = this.openSession();

		Query query = session
				.createQuery("Select version from ApplicationVersion version where version.versionPk.version=:version and version.versionPk.application.nameSpace = :nameSpace and version.versionPk.application.user.email = :devEmail");

		query.setParameter("version", versionPk.getVersion());
		query.setParameter("nameSpace", versionPk.getApp().getNameSpace());
		query.setParameter("devEmail", devEmail);

		ApplicationVersion version = (ApplicationVersion) query.uniqueResult();
		return version;

	}

	public List<Downloader> getAllDevicesFor(Application application)
			throws HibernateException {

		Session session = this.openSession();
		String strQuery = "select app.downloaders from Application app where app.nameSpace = :nameSpace and app.user.email = :devEmail";
		Query query = session.createQuery(strQuery);
		query.setParameter("devEmail", application.getUser().getEmail());
		query.setParameter("nameSpace", application.getNameSpace());

		@SuppressWarnings("unchecked")
		List<Downloader> downloaders = query.list();
		return downloaders;

	}

}
